package shard.db.demo.jdbc;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import io.shardingsphere.api.config.ShardingRuleConfiguration;
import io.shardingsphere.api.config.TableRuleConfiguration;
import io.shardingsphere.api.config.strategy.InlineShardingStrategyConfiguration;
import io.shardingsphere.shardingjdbc.api.ShardingDataSourceFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Configuration
public class ShardingConf {


    public Map<String, DataSource> dataSourceMap() {
        Map<String, DataSource> dataSourceMap = new HashMap<>();
        dataSourceMap.put("ds1", ds1());
        dataSourceMap.put("ds2", ds2());
        return dataSourceMap;
    }


    /**
     * @return
     * @desc 配置数据库
     */
    @Bean(name = "ds1")
    public DataSource ds1() {
        HikariConfig hikariConfig = new HikariConfig();
        hikariConfig.setDriverClassName("com.mysql.jdbc.Driver");
        hikariConfig.setJdbcUrl("jdbc:mysql://localhost:3306/ds1?useSSL=true");
        hikariConfig.setUsername("root");
        hikariConfig.setPassword("root");

        DataSource dataSource = new HikariDataSource(hikariConfig);

        return dataSource;
    }

    @Bean(name = "ds2")
    public DataSource ds2() {
        HikariConfig hikariConfig = new HikariConfig();
        hikariConfig.setDriverClassName("com.mysql.jdbc.Driver");
        hikariConfig.setJdbcUrl("jdbc:mysql://localhost:3306/ds2?useSSL=true");
        hikariConfig.setUsername("root");
        hikariConfig.setPassword("root");
        DataSource dataSource = new HikariDataSource(hikariConfig);

        return dataSource;
    }


    @Bean(name = "dataSource")
    @Qualifier(value = "dataSource")
    public DataSource dataSource() {

        TableRuleConfiguration tableRuleConfig = table1RuleConf();
        // 配置分片规则
        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
        shardingRuleConfig.getTableRuleConfigs().add(tableRuleConfig);
        Properties p = new Properties();
        p.setProperty("sql.show", Boolean.TRUE.toString());
        // 获取数据源对象
        DataSource dataSource = null;
        try {
            dataSource = ShardingDataSourceFactory.createDataSource(dataSourceMap(), shardingRuleConfig, new ConcurrentHashMap(), p);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return dataSource;
    }

    /**
     * @return
     * @desc Table1 策略
     */
    private TableRuleConfiguration table1RuleConf() {
        // 配置表规则
        TableRuleConfiguration tableRuleConfig = new TableRuleConfiguration();
        tableRuleConfig.setLogicTable("table");
        tableRuleConfig.setActualDataNodes("ds${1..2}.table${1..2}");
        tableRuleConfig.setKeyGeneratorColumnName("id");
        // 配置分库 + 分表策略
//        tableRuleConfig.setDatabaseShardingStrategyConfig(new InlineShardingStrategyConfiguration("id", "ds${id % 2}"));
        tableRuleConfig.setTableShardingStrategyConfig(new InlineShardingStrategyConfiguration("id", "table${id % 2}"));
        return tableRuleConfig;
    }

    @Bean(name = "js")
    @Qualifier(value = "js")
    public JdbcTemplate jdbcTemplate(@Qualifier(value = "dataSource") DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }


}
